package com.uminho.egendme;



import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONException;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

import com.uminho.exceptions.DestroyException;
import com.uminho.exceptions.InvalidOAuthParametersError;
import com.uminho.exceptions.InvalidOAuthTokenError;
import com.uminho.exceptions.NotAllowedError;
import com.uminho.exceptions.OAuthServiceFailureError;
import com.uminho.exceptions.SaveException;
import com.uminho.http.Webservice;
import com.uminho.preferences.PreferencesHandler;
import com.uminho.tools.NotificationsDef;

/****c* egendme/Notifications
 * DESCRIPTION
 * Classe responsável por oferecer suporte ao serviço de Notificações
 ****
 */

public class Notifications extends Service {
	private NotificationManager mNM;
	private Handler mHandler = new Handler();
	private Runnable getNoti;
	private Timer timer;
	// Unique Identification Number for the Notification.
	// We use it on Notification start, and to cancel it.
	//private int NOTIFICATION = R.string.local_service_started;

	/**
	 * Class for clients to access.  Because we know this service always
	 * runs in the same process as its clients, we don't need to deal with
	 * IPC.
	 */
	public class LocalBinder extends Binder {
		Notifications getService() {
			return Notifications.this;
		}
	}

	/****f* Notifications/onCreate
	 * DESCRIPTION
	 * Método executado para criar a o serviço
	 * RESULT
	 * Serviço criado
	 ****
	 */
	@Override
	public void onCreate() {
		mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
		if (this.timer != null) {
			this.timer.cancel();
		}

	}

	/****f* Notifications/onStartCommand
	 * DESCRIPTION
	 * Método executado quando é iniciado o serviço
	 * INPUTS
	 * Intent da actividade que inicia o serviço, flag de controlo para saber o tipo de pedido, e um id único para identificação do pedido
	 * RESULT
	 * Serviço iniciado
	 ****
	 */


	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i("LocalService", "Received start id " + startId + ": " + intent);

		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
		String result=prefs.getString("selected_notification_time_option", "60");
		
		Log.d("Service Result", result);
		int time = Integer.parseInt(result);
		this.timer = new Timer();
		this.timer.schedule(new PostingServiceTimeTask(this),0, (60000*time));
		// We want this service to continue running until it is explicitly
		// stopped, so return sticky.
		return 1;
	}

	
	@Override
	public void onDestroy() {
		// Cancel the persistent notification.
		//mNM.cancel(NOTIFICATION);

		// Tell the user we stopped.
		mHandler.removeCallbacks(getNoti);
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	// This is the object that receives interactions from clients.  See
	// RemoteService for a more complete example.
	private final IBinder mBinder = new LocalBinder();

	/**
	 * Show a notification while this service is running.
	 */

	/****f* Notifications/showNotification
	 * DESCRIPTION
	 * Método executado para mostrar notificações enquanto o serviço está a correr
	 * INPUTS
	 * O identificador do recurso(icon) da notificação, o título da notificação, a descrição da notificação e o identificador único da notificação
	 * RESULT
	 * É apresentada a notificação no sistema
	 ****
	 */
	private void showNotification(int resource, String title, String description, int notificationsId) {
		// In this sample, we'll use the same text for the ticker and the expanded notification

		// Set the icon, scrolling text and timestamp
		Notification notification = new Notification(NotificationsDef.notificationResourceId(title), getString(NotificationsDef.notificationStringId(title)),
				System.currentTimeMillis());

		// The PendingIntent to launch our activity if the user selects this notification
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				new Intent(this, Dashboard.class), 0);

		// Set the info for the views that show in the notification panel.
		notification.setLatestEventInfo(this, getString(NotificationsDef.notificationStringId(title)),
				description, contentIntent);

		// Set the default sound.
		notification.defaults |= Notification.DEFAULT_SOUND;


		// Send the notification.
		mNM.notify(notificationsId, notification);


	}


	/****f* Notifications/readNotifications
	 * DESCRIPTION
	 * Método executado para ler as notificações do servidor
	 * RESULT
	 * Lista de notificações
	 ****
	 */
	private void readNotifications(){
		Webservice ws = Webservice.getInstance(); 
		ArrayList<com.uminho.objects.Notification> notifications = null;

		try {
			notifications = ws.getNotifications();
			int i=0;
			for(com.uminho.objects.Notification n: notifications){
				if(PreferencesHandler.isSelected(n.getNotificationType()+"_key", Notifications.this)){
				showNotification(0, n.getNotificationType(),"",i);
				i++;
				}
			}
		} catch (ClientProtocolException e) {
			Toast.makeText(Notifications.this,getString(R.string.impossiblereachtheserver),Toast.LENGTH_LONG).show();
			e.printStackTrace();
		} catch (URISyntaxException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidOAuthParametersError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidOAuthTokenError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (OAuthServiceFailureError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NotAllowedError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SaveException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DestroyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}



	}

	/****f* Notifications/getRefreshTime
	 * DESCRIPTION
	 * Método executado para ler as preferências do utilizador e assim saber de quanto em quanto tempo o utilizador quer fazer refresh
	 * INPUTS
	 * Contexto da aplicação
	 * RESULT
	 * Valor com o tempo em milisegundos de quanto em quanto tempo o utilizador quer ler os updates
	 ****
	 */
	public static int getRefreshTime(Context c){
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
		String result=prefs.getString("selected_notification_time_option", "");
		if(result!=null){
			int res=Integer.parseInt(result);
			return res;
		}
		else{
			prefs.edit().putString("selected_notification_time_option", "60").commit();
			return 60;
		}


	}

	/****c* egendme/PostingServiceTimeTask
	 * DESCRIPTION
	 * Classe responsável por executar os pedidos das notificações em background
	 ****
	 */
	class PostingServiceTimeTask extends TimerTask {
		private Service service;
		private PostingServiceTimeTask(Service service) {
			this.service = service;
		}

		public void run() {
			readNotifications();
		}
	}



}
